// 定义图层类型枚举
enum LayerType {
    Point = 'circle',
    Line = 'line',
    Fill = 'fill',
    Symbol = 'symbol',
    Raster = 'raster',
    geojson = 'geojson',
    custom = 'custom'
}

// 定义图层配置接口
interface LayerConfig {
    id: string;
    type: LayerType;
    source?: mapboxgl.AnySourceData;
    paint?: mapboxgl.LayerPaintPropertyMap;
    layout?: mapboxgl.LayerLayoutPropertyMap;
    filter?: any;
    beforeLayerId?: string; // 新增属性，用于指定添加图层时的前置图层 ID
    properties?: any,
    onAdd?: any, render?: any, renderingMode?: any
}

// 定义图层管理器状态
interface LayerManagerState {
    map: mapboxgl.Map;
    layerOrder: string[];
}

// 初始化图层管理器，传入一个mapboxgl.Map对象作为参数
function initLayerManager(map: mapboxgl.Map): LayerManagerState {
    // 返回一个包含map和layerOrder的LayerManagerState对象
    return {
        map,
        layerOrder: []
    };
}

// 添加图层函数
function addLayer(state: LayerManagerState, config: LayerConfig): void {
    const { id, type, source, paint, layout, beforeLayerId, properties, filter, onAdd, render, renderingMode } = config;

    // 判断图层是否已经存在，如果存在则直接返回
    if (state.map.getLayer(id)) {
        console.log(`图层 ${id} 已存在，跳过添加操作。`);
        return;
    }

    // 如果state.map中没有id对应的source，则添加source
    if (!state.map.getSource(id) && source) {
        try {
            state.map.addSource(id, source);
        } catch (error) {
            console.error(`添加数据源 ${id} 时出错:`, error);
            return;
        }
    }

    let layerConfig = {
        id,
        type,
        source: id,
        paint: paint ? paint : {},
        layout: layout ? layout : {},
        properties: properties ? properties : {},
    };

    if (filter) {
        layerConfig.filter = filter;
    }
    if (onAdd) {
        layerConfig.onAdd = onAdd;
    }
    if (render) {
        layerConfig.render = render;
    }
    if (renderingMode) {
        layerConfig.renderingMode = renderingMode;
    }

    // 如果有beforeLayerId，则在beforeLayerId之前添加图层
    try {
        if (beforeLayerId) {
            state.map.addLayer(layerConfig, beforeLayerId);
        } else {
            state.map.addLayer(layerConfig);
        }
    } catch (error) {
        console.error(`添加图层 ${id} 时出错:`, error);
        return;
    }

    // 将id添加到layerOrder中
    if (!state.layerOrder.includes(id)) {
        state.layerOrder.push(id);
    }
}

// 函数removeLayer用于从LayerManagerState中移除指定id的图层
function removeLayer(state: LayerManagerState, layerId: string): void {
    // 如果state.map中存在指定id的图层，则移除该图层
    if (state.map.getLayer(layerId)) {
        state.map.removeLayer(layerId);
    }
    // 如果state.map中存在指定id的源，则移除该源
    if (state.map.getSource(layerId)) {
        state.map.removeSource(layerId);
    }
    // 获取指定id在state.layerOrder中的索引
    const index = state.layerOrder.indexOf(layerId);
    // 如果索引大于-1，则说明该图层存在于state.layerOrder中，将其从state.layerOrder中移除
    if (index > -1) {
        state.layerOrder.splice(index, 1);
    }
}


// 移除所有图层和数据源的函数
function removeAllLayers(state: LayerManagerState): void {
    const usedSources = new Set<string>();

    // 先移除所有图层
    state.map.getStyle().layers.forEach((layer: { id: string; source: string }) => {
        if (state.map.getLayer(layer.id)) {
            state.map.removeLayer(layer.id);
            usedSources.add(layer.source);
        }
    });

    // 再移除所有使用过的数据源
    usedSources.forEach((sourceId) => {
        if (state.map.getSource(sourceId)) {
            state.map.removeSource(sourceId);
        }
    });

    // 清空 state.layerOrder
    state.layerOrder = [];
}


// 根据传入的state和layerId，显示指定图层
function showLayer(state: LayerManagerState, layerId: string): void {
    // 如果state中的map存在指定layerId的图层
    if (state.map.getLayer(layerId)) {
        // 将指定图层的可见性设置为可见
        state.map.setLayoutProperty(layerId, 'visibility', 'visible');
    }
}


// 隐藏图层函数
// 参数：state：LayerManagerState，layerId：string
// 返回值：void
function hideLayer(state: LayerManagerState, layerId: string): void {
    // 如果state.map中存在layerId对应的图层
    if (state.map.getLayer(layerId)) {
        // 将该图层的可见性设置为'none'
        state.map.setLayoutProperty(layerId, 'visibility', 'none');
    }
}

// 函数：判断state中是否存在layerId对应的图层
// 参数：state：LayerManagerState类型，layerId：string类型
// 返回值：boolean类型，表示是否存在layerId对应的图层
function hasLayer(state: LayerManagerState, layerId: string): boolean {
    // 获取state中layerId对应的图层
    return state.map.getLayer(layerId) !== undefined;
}

// 根据传入的state和layerId获取对应的mapboxgl.Layer对象
function getLayerInfo(state: LayerManagerState, layerId: string): mapboxgl.Layer | undefined {
    // 从state的map对象中获取对应的layerId的Layer对象
    return state.map.getLayer(layerId);
}

// 更新图层样式
// state: 图层管理状态
// layerId: 图层ID
// paint: 图层样式属性
// layout: 图层布局属性
function updateLayerStyle(
    state: LayerManagerState,
    layerId: string,
    paint?: mapboxgl.LayerPaintPropertyMap,
    layout?: mapboxgl.LayerLayoutPropertyMap
): void {
    // 如果地图中存在该图层
    if (state.map.getLayer(layerId)) {
        // 如果存在图层样式属性
        if (paint) {
            // 遍历图层样式属性
            for (const [key, value] of Object.entries(paint)) {
                // 设置图层样式属性
                state.map.setPaintProperty(layerId, key, value);
            }
        }
        // 如果存在图层布局属性
        if (layout) {
            // 遍历图层布局属性
            for (const [key, value] of Object.entries(layout)) {
                // 设置图层布局属性
                state.map.setLayoutProperty(layerId, key, value);
            }
        }
    }
}

// 根据传入的图层ID，切换图层的可见性
function toggleLayerVisibility(state: LayerManagerState, layerId: string): void {
    // 判断图层是否存在
    if (state.map.getLayer(layerId)) {
        // 获取图层的可见性属性
        const visibility = state.map.getLayoutProperty(layerId, 'visibility') as string;
        // 如果图层可见，则隐藏图层
        if (visibility === 'visible') {
            hideLayer(state, layerId);
            // 如果图层不可见，则显示图层
        } else {
            showLayer(state, layerId);
        }
    }
}

// 将图层移动到最上层
function moveLayerToTop(state: LayerManagerState, layerId: string): void {
    // 如果图层存在
    if (state.map.getLayer(layerId)) {
        // 将图层移动到最上层
        state.map.moveLayer(layerId);
        // 获取图层的索引
        const index = state.layerOrder.indexOf(layerId);
        // 如果图层存在
        if (index > -1) {
            // 从图层顺序中移除图层
            state.layerOrder.splice(index, 1);
            // 将图层添加到图层顺序的末尾
            state.layerOrder.push(layerId);
        }
    }
}

// 将图层移动到底部
function moveLayerToBottom(state: LayerManagerState, layerId: string): void {
    // 如果图层存在
    if (state.map.getLayer(layerId)) {
        // 获取图层顺序中的第一个图层ID
        const firstLayerId = state.layerOrder[0];
        // 如果第一个图层ID存在
        if (firstLayerId) {
            // 将当前图层移动到第一个图层之前
            state.map.moveLayer(layerId, firstLayerId);
        }
        // 获取当前图层在图层顺序中的索引
        const index = state.layerOrder.indexOf(layerId);
        // 如果索引大于-1，说明图层存在
        if (index > -1) {
            // 从图层顺序中删除当前图层
            state.layerOrder.splice(index, 1);
            // 将当前图层添加到图层顺序的第一个位置
            state.layerOrder.unshift(layerId);
        }
    }
}

// 将指定图层移动到另一个图层之上
function moveLayerAbove(
    // 图层管理器状态
    state: LayerManagerState,
    // 要移动的图层的ID
    layerId: string,
    // 要移动到的图层的ID
    aboveLayerId: string
): void {
    // 如果要移动的图层和要移动到的图层都存在
    if (state.map.getLayer(layerId) && state.map.getLayer(aboveLayerId)) {
        // 将要移动的图层移动到要移动到的图层之上
        state.map.moveLayer(layerId, aboveLayerId);
        // 获取要移动的图层的索引
        const index = state.layerOrder.indexOf(layerId);
        // 获取要移动到的图层的索引
        const aboveIndex = state.layerOrder.indexOf(aboveLayerId);
        // 如果要移动的图层和要移动到的图层都存在
        if (index > -1 && aboveIndex > -1) {
            // 从图层顺序中删除要移动的图层
            state.layerOrder.splice(index, 1);
            // 在要移动到的图层的索引之后插入要移动的图层
            state.layerOrder.splice(aboveIndex + 1, 0, layerId);
        }
    }
}

// 将指定图层移动到指定图层的下方
function moveLayerBelow(
    // 图层管理器状态
    state: LayerManagerState,
    // 要移动的图层的ID
    layerId: string,
    // 要移动到的图层的ID
    belowLayerId: string
): void {
    // 如果要移动的图层和要移动到的图层都存在
    if (state.map.getLayer(layerId) && state.map.getLayer(belowLayerId)) {
        // 获取要移动到的图层的索引
        const belowIndex = state.layerOrder.indexOf(belowLayerId);
        // 获取要移动到的图层之前的图层的ID
        const beforeLayerId = belowIndex > 0 ? state.layerOrder[belowIndex - 1] : undefined;
        // 将要移动的图层移动到指定位置
        state.map.moveLayer(layerId, beforeLayerId);
        // 获取要移动的图层的索引
        const index = state.layerOrder.indexOf(layerId);
        // 如果要移动的图层和要移动到的图层都存在
        if (index > -1 && belowIndex > -1) {
            // 从图层顺序中删除要移动的图层
            state.layerOrder.splice(index, 1);
            // 在要移动到的图层之后插入要移动的图层
            state.layerOrder.splice(belowIndex, 0, layerId);
        }
    }
}

// 根据LayerManagerState获取所有图层的id
function getAllLayerIds(state: LayerManagerState): string[] {
    // 返回state中的layerOrder数组
    return state.layerOrder;
}

export {
    LayerType,
    initLayerManager,
    addLayer,
    removeLayer,
    showLayer,
    hideLayer,
    hasLayer,
    getLayerInfo,
    updateLayerStyle,
    toggleLayerVisibility,
    moveLayerToTop,
    moveLayerToBottom,
    moveLayerAbove,
    moveLayerBelow,
    getAllLayerIds,
    removeAllLayers
};
export type { LayerConfig };